home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / m_actor.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-07  |  14.3 KB  |  610 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // g_actor.c
  21.  
  22. #include "g_local.h"
  23. #include "m_actor.h"
  24.  
  25. #define    MAX_ACTOR_NAMES        8
  26. char *actor_names[MAX_ACTOR_NAMES] =
  27. {
  28.     "Hellrot",
  29.     "Tokay",
  30.     "Killme",
  31.     "Disruptor",
  32.     "Adrianator",
  33.     "Rambear",
  34.     "Titus",
  35.     "Bitterman"
  36. };
  37.  
  38.  
  39. mframe_t actor_frames_stand [] =
  40. {
  41.     ai_stand, 0, NULL,
  42.     ai_stand, 0, NULL,
  43.     ai_stand, 0, NULL,
  44.     ai_stand, 0, NULL,
  45.     ai_stand, 0, NULL,
  46.     ai_stand, 0, NULL,
  47.     ai_stand, 0, NULL,
  48.     ai_stand, 0, NULL,
  49.     ai_stand, 0, NULL,
  50.     ai_stand, 0, NULL,
  51.  
  52.     ai_stand, 0, NULL,
  53.     ai_stand, 0, NULL,
  54.     ai_stand, 0, NULL,
  55.     ai_stand, 0, NULL,
  56.     ai_stand, 0, NULL,
  57.     ai_stand, 0, NULL,
  58.     ai_stand, 0, NULL,
  59.     ai_stand, 0, NULL,
  60.     ai_stand, 0, NULL,
  61.     ai_stand, 0, NULL,
  62.  
  63.     ai_stand, 0, NULL,
  64.     ai_stand, 0, NULL,
  65.     ai_stand, 0, NULL,
  66.     ai_stand, 0, NULL,
  67.     ai_stand, 0, NULL,
  68.     ai_stand, 0, NULL,
  69.     ai_stand, 0, NULL,
  70.     ai_stand, 0, NULL,
  71.     ai_stand, 0, NULL,
  72.     ai_stand, 0, NULL,
  73.  
  74.     ai_stand, 0, NULL,
  75.     ai_stand, 0, NULL,
  76.     ai_stand, 0, NULL,
  77.     ai_stand, 0, NULL,
  78.     ai_stand, 0, NULL,
  79.     ai_stand, 0, NULL,
  80.     ai_stand, 0, NULL,
  81.     ai_stand, 0, NULL,
  82.     ai_stand, 0, NULL,
  83.     ai_stand, 0, NULL
  84. };
  85. mmove_t actor_move_stand = {FRAME_stand101, FRAME_stand140, actor_frames_stand, NULL};
  86.  
  87. void actor_stand (edict_t *self)
  88. {
  89.     self->monsterinfo.currentmove = &actor_move_stand;
  90.  
  91.     // randomize on startup
  92.     if (level.time < 1.0)
  93.         self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1));
  94. }
  95.  
  96.  
  97. mframe_t actor_frames_walk [] =
  98. {
  99.     ai_walk, 0,  NULL,
  100.     ai_walk, 6,  NULL,
  101.     ai_walk, 10, NULL,
  102.     ai_walk, 3,  NULL,
  103.     ai_walk, 2,  NULL,
  104.     ai_walk, 7,  NULL,
  105.     ai_walk, 10, NULL,
  106.     ai_walk, 1,  NULL,
  107.     ai_walk, 4,  NULL,
  108.     ai_walk, 0,  NULL,
  109.     ai_walk, 0,  NULL
  110. };
  111. mmove_t actor_move_walk = {FRAME_walk01, FRAME_walk08, actor_frames_walk, NULL};
  112.  
  113. void actor_walk (edict_t *self)
  114. {
  115.     self->monsterinfo.currentmove = &actor_move_walk;
  116. }
  117.  
  118.  
  119. mframe_t actor_frames_run [] =
  120. {
  121.     ai_run, 4,  NULL,
  122.     ai_run, 15, NULL,
  123.     ai_run, 15, NULL,
  124.     ai_run, 8,  NULL,
  125.     ai_run, 20, NULL,
  126.     ai_run, 15, NULL,
  127.     ai_run, 8,  NULL,
  128.     ai_run, 17, NULL,
  129.     ai_run, 12, NULL,
  130.     ai_run, -2, NULL,
  131.     ai_run, -2, NULL,
  132.     ai_run, -1, NULL
  133. };
  134. mmove_t actor_move_run = {FRAME_run02, FRAME_run07, actor_frames_run, NULL};
  135.  
  136. void actor_run (edict_t *self)
  137. {
  138.     if ((level.time < self->pain_debounce_time) && (!self->enemy))
  139.     {
  140.         if (self->movetarget)
  141.             actor_walk(self);
  142.         else
  143.             actor_stand(self);
  144.         return;
  145.     }
  146.  
  147.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  148.     {
  149.         actor_stand(self);
  150.         return;
  151.     }
  152.  
  153.     self->monsterinfo.currentmove = &actor_move_run;
  154. }
  155.  
  156.  
  157. mframe_t actor_frames_pain1 [] =
  158. {
  159.     ai_move, -5, NULL,
  160.     ai_move, 4,  NULL,
  161.     ai_move, 1,  NULL
  162. };
  163. mmove_t actor_move_pain1 = {FRAME_pain101, FRAME_pain103, actor_frames_pain1, actor_run};
  164.  
  165. mframe_t actor_frames_pain2 [] =
  166. {
  167.     ai_move, -4, NULL,
  168.     ai_move, 4,  NULL,
  169.     ai_move, 0,  NULL
  170. };
  171. mmove_t actor_move_pain2 = {FRAME_pain201, FRAME_pain203, actor_frames_pain2, actor_run};
  172.  
  173. mframe_t actor_frames_pain3 [] =
  174. {
  175.     ai_move, -1, NULL,
  176.     ai_move, 1,  NULL,
  177.     ai_move, 0,  NULL
  178. };
  179. mmove_t actor_move_pain3 = {FRAME_pain301, FRAME_pain303, actor_frames_pain3, actor_run};
  180.  
  181. mframe_t actor_frames_flipoff [] =
  182. {
  183.     ai_turn, 0,  NULL,
  184.     ai_turn, 0,  NULL,
  185.     ai_turn, 0,  NULL,
  186.     ai_turn, 0,  NULL,
  187.     ai_turn, 0,  NULL,
  188.     ai_turn, 0,  NULL,
  189.     ai_turn, 0,  NULL,
  190.     ai_turn, 0,  NULL,
  191.     ai_turn, 0,  NULL,
  192.     ai_turn, 0,  NULL,
  193.     ai_turn, 0,  NULL,
  194.     ai_turn, 0,  NULL,
  195.     ai_turn, 0,  NULL,
  196.     ai_turn, 0,  NULL
  197. };
  198. mmove_t actor_move_flipoff = {FRAME_flip01, FRAME_flip14, actor_frames_flipoff, actor_run};
  199.  
  200. mframe_t actor_frames_taunt [] =
  201. {
  202.     ai_turn, 0,  NULL,
  203.     ai_turn, 0,  NULL,
  204.     ai_turn, 0,  NULL,
  205.     ai_turn, 0,  NULL,
  206.     ai_turn, 0,  NULL,
  207.     ai_turn, 0,  NULL,
  208.     ai_turn, 0,  NULL,
  209.     ai_turn, 0,  NULL,
  210.     ai_turn, 0,  NULL,
  211.     ai_turn, 0,  NULL,
  212.     ai_turn, 0,  NULL,
  213.     ai_turn, 0,  NULL,
  214.     ai_turn, 0,  NULL,
  215.     ai_turn, 0,  NULL,
  216.     ai_turn, 0,  NULL,
  217.     ai_turn, 0,  NULL,
  218.     ai_turn, 0,  NULL
  219. };
  220. mmove_t actor_move_taunt = {FRAME_taunt01, FRAME_taunt17, actor_frames_taunt, actor_run};
  221.  
  222. char *messages[] =
  223. {
  224.     "Watch it",
  225.     "#$@*&",
  226.     "Idiot",
  227.     "Check your targets"
  228. };
  229.  
  230. void actor_pain (edict_t *self, edict_t *other, float kick, int damage)
  231. {
  232.     int        n;
  233.  
  234.     if (self->health < (self->max_health / 2))
  235.         self->s.skinnum = 1;
  236.  
  237.     if (level.time < self->pain_debounce_time)
  238.         return;
  239.  
  240.     self->pain_debounce_time = level.time + 3;
  241. //    gi.sound (self, CHAN_VOICE, actor.sound_pain, 1, ATTN_NORM, 0);
  242.  
  243.     if ((other->client) && (random() < 0.4))
  244.     {
  245.         vec3_t    v;
  246.         char    *name;
  247.  
  248.         VectorSubtract (other->s.origin, self->s.origin, v);
  249.         self->ideal_yaw = vectoyaw (v);
  250.         if (random() < 0.5)
  251.             self->monsterinfo.currentmove = &actor_move_flipoff;
  252.         else
  253.             self->monsterinfo.currentmove = &actor_move_taunt;
  254.         name = actor_names[(self - g_edicts)%MAX_ACTOR_NAMES];
  255.         gi.cprintf (other, PRINT_CHAT, "%s: %s!\n", name, messages[rand()%3]);
  256.         return;
  257.     }
  258.  
  259.     n = rand() % 3;
  260.     if (n == 0)
  261.         self->monsterinfo.currentmove = &actor_move_pain1;
  262.     else if (n == 1)
  263.         self->monsterinfo.currentmove = &actor_move_pain2;
  264.     else
  265.         self->monsterinfo.currentmove = &actor_move_pain3;
  266. }
  267.  
  268.  
  269. void actorMachineGun (edict_t *self)
  270. {
  271.     vec3_t    start, target;
  272.     vec3_t    forward, right;
  273.  
  274.     AngleVectors (self->s.angles, forward, right, NULL);
  275.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_ACTOR_MACHINEGUN_1], forward, right, start);
  276.     if (self->enemy)
  277.     {
  278.         if (self->enemy->health > 0)
  279.         {
  280.             VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  281.             target[2] += self->enemy->viewheight;
  282.         }
  283.         else
  284.         {
  285.             VectorCopy (self->enemy->absmin, target);
  286.             target[2] += (self->enemy->size[2] / 2);
  287.         }
  288.         VectorSubtract (target, start, forward);
  289.         VectorNormalize (forward);
  290.     }
  291.     else
  292.     {
  293.         AngleVectors (self->s.angles, forward, NULL, NULL);
  294.     }
  295.     monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_ACTOR_MACHINEGUN_1);
  296. }
  297.  
  298.  
  299. void actor_dead (edict_t *self)
  300. {
  301.     VectorSet (self->mins, -16, -16, -24);
  302.     VectorSet (self->maxs, 16, 16, -8);
  303.     self->movetype = MOVETYPE_TOSS;
  304.     self->svflags |= SVF_DEADMONSTER;
  305.     self->nextthink = 0;
  306.     gi.linkentity (self);
  307. }
  308.  
  309. mframe_t actor_frames_death1 [] =
  310. {
  311.     ai_move, 0,   NULL,
  312.     ai_move, 0,   NULL,
  313.     ai_move, -13, NULL,
  314.     ai_move, 14,  NULL,
  315.     ai_move, 3,   NULL,
  316.     ai_move, -2,  NULL,
  317.     ai_move, 1,   NULL
  318. };
  319. mmove_t actor_move_death1 = {FRAME_death101, FRAME_death107, actor_frames_death1, actor_dead};
  320.  
  321. mframe_t actor_frames_death2 [] =
  322. {
  323.     ai_move, 0,   NULL,
  324.     ai_move, 7,   NULL,
  325.     ai_move, -6,  NULL,
  326.     ai_move, -5,  NULL,
  327.     ai_move, 1,   NULL,
  328.     ai_move, 0,   NULL,
  329.     ai_move, -1,  NULL,
  330.     ai_move, -2,  NULL,
  331.     ai_move, -1,  NULL,
  332.     ai_move, -9,  NULL,
  333.     ai_move, -13, NULL,
  334.     ai_move, -13, NULL,
  335.     ai_move, 0,   NULL
  336. };
  337. mmove_t actor_move_death2 = {FRAME_death201, FRAME_death213, actor_frames_death2, actor_dead};
  338.  
  339. void actor_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  340. {
  341.     int        n;
  342.  
  343. // check for gib
  344.     if (self->health <= -80)
  345.     {
  346. //        gi.sound (self, CHAN_VOICE, actor.sound_gib, 1, ATTN_NORM, 0);
  347.         for (n= 0; n < 2; n++)
  348.             ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  349.         for (n= 0; n < 4; n++)
  350.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  351.         ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  352.         self->deadflag = DEAD_DEAD;
  353.         return;
  354.     }
  355.  
  356.     if (self->deadflag == DEAD_DEAD)
  357.         return;
  358.  
  359. // regular death
  360. //    gi.sound (self, CHAN_VOICE, actor.sound_die, 1, ATTN_NORM, 0);
  361.     self->deadflag = DEAD_DEAD;
  362.     self->takedamage = DAMAGE_YES;
  363.  
  364.     n = rand() % 2;
  365.     if (n == 0)
  366.         self->monsterinfo.currentmove = &actor_move_death1;
  367.     else
  368.         self->monsterinfo.currentmove = &actor_move_death2;
  369. }
  370.  
  371.  
  372. void actor_fire (edict_t *self)
  373. {
  374.     actorMachineGun (self);
  375.  
  376.     if (level.time >= self->monsterinfo.pausetime)
  377.         self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  378.     else
  379.         self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  380. }
  381.  
  382. mframe_t actor_frames_attack [] =
  383. {
  384.     ai_charge, -2,  actor_fire,
  385.     ai_charge, -2,  NULL,
  386.     ai_charge, 3,   NULL,
  387.     ai_charge, 2,   NULL
  388. };
  389. mmove_t actor_move_attack = {FRAME_attak01, FRAME_attak04, actor_frames_attack, actor_run};
  390.  
  391. void actor_attack(edict_t *self)
  392. {
  393.     int        n;
  394.  
  395.     self->monsterinfo.currentmove = &actor_move_attack;
  396.     n = (rand() & 15) + 3 + 7;
  397.     self->monsterinfo.pausetime = level.time + n * FRAMETIME;
  398. }
  399.  
  400.  
  401. void actor_use (edict_t *self, edict_t *other, edict_t *activator)
  402. {
  403.     vec3_t        v;
  404.  
  405.     self->goalentity = self->movetarget = G_PickTarget(self->target);
  406.     if ((!self->movetarget) || (strcmp(self->movetarget->classname, "target_actor") != 0))
  407.     {
  408.         gi.dprintf ("%s has bad target %s at %s\n", self->classname, self->target, vtos(self->s.origin));
  409.         self->target = NULL;
  410.         self->monsterinfo.pausetime = 100000000;
  411.         self->monsterinfo.stand (self);
  412.         return;
  413.     }
  414.  
  415.     VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
  416.     self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v);
  417.     self->monsterinfo.walk (self);
  418.     self->target = NULL;
  419. }
  420.  
  421.  
  422. /*QUAKED misc_actor (1 .5 0) (-16 -16 -24) (16 16 32)
  423. */
  424.  
  425. void SP_misc_actor (edict_t *self)
  426. {
  427.     if (deathmatch->value)
  428.     {
  429.         G_FreeEdict (self);
  430.         return;
  431.     }
  432.  
  433.     if (!self->targetname)
  434.     {
  435.         gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin));
  436.         G_FreeEdict (self);
  437.         return;
  438.     }
  439.  
  440.     if (!self->target)
  441.     {
  442.         gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin));
  443.         G_FreeEdict (self);
  444.         return;
  445.     }
  446.  
  447.     self->movetype = MOVETYPE_STEP;
  448.     self->solid = SOLID_BBOX;
  449.     self->s.modelindex = gi.modelindex("players/male/tris.md2");
  450.     VectorSet (self->mins, -16, -16, -24);
  451.     VectorSet (self->maxs, 16, 16, 32);
  452.  
  453.     if (!self->health)
  454.         self->health = 100;
  455.     self->mass = 200;
  456.  
  457.     self->pain = actor_pain;
  458.     self->die = actor_die;
  459.  
  460.     self->monsterinfo.stand = actor_stand;
  461.     self->monsterinfo.walk = actor_walk;
  462.     self->monsterinfo.run = actor_run;
  463.     self->monsterinfo.attack = actor_attack;
  464.     self->monsterinfo.melee = NULL;
  465.     self->monsterinfo.sight = NULL;
  466.  
  467.     self->monsterinfo.aiflags |= AI_GOOD_GUY;
  468.  
  469.     gi.linkentity (self);
  470.  
  471.     self->monsterinfo.currentmove = &actor_move_stand;
  472.     self->monsterinfo.scale = MODEL_SCALE;
  473.  
  474.     walkmonster_start (self);
  475.  
  476.     // actors always start in a dormant state, they *must* be used to get going
  477.     self->use = actor_use;
  478. }
  479.  
  480.  
  481. /*QUAKED target_actor (.5 .3 0) (-8 -8 -8) (8 8 8) JUMP SHOOT ATTACK x HOLD BRUTAL
  482. JUMP            jump in set direction upon reaching this target
  483. SHOOT            take a single shot at the pathtarget
  484. ATTACK            attack pathtarget until it or actor is dead 
  485.  
  486. "target"        next target_actor
  487. "pathtarget"    target of any action to be taken at this point
  488. "wait"            amount of time actor should pause at this point
  489. "message"        actor will "say" this to the player
  490.  
  491. for JUMP only:
  492. "speed"            speed thrown forward (default 200)
  493. "height"        speed thrown upwards (default 200)
  494. */
  495.  
  496. void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
  497. {
  498.     vec3_t    v;
  499.  
  500.     if (other->movetarget != self)
  501.         return;
  502.     
  503.     if (other->enemy)
  504.         return;
  505.  
  506.     other->goalentity = other->movetarget = NULL;
  507.  
  508.     if (self->message)
  509.     {
  510.         int        n;
  511.         edict_t    *ent;
  512.  
  513.         for (n = 1; n <= game.maxclients; n++)
  514.         {
  515.             ent = &g_edicts[n];
  516.             if (!ent->inuse)
  517.                 continue;
  518.             gi.cprintf (ent, PRINT_CHAT, "%s: %s\n", actor_names[(other - g_edicts)%MAX_ACTOR_NAMES], self->message);
  519.         }
  520.     }
  521.  
  522.     if (self->spawnflags & 1)        //jump
  523.     {
  524.         other->velocity[0] = self->movedir[0] * self->speed;
  525.         other->velocity[1] = self->movedir[1] * self->speed;
  526.         
  527.         if (other->groundentity)
  528.         {
  529.             other->groundentity = NULL;
  530.             other->velocity[2] = self->movedir[2];
  531.             gi.sound(other, CHAN_VOICE, gi.soundindex("player/male/jump1.wav"), 1, ATTN_NORM, 0);
  532.         }
  533.     }
  534.  
  535.     if (self->spawnflags & 2)    //shoot
  536.     {
  537.     }
  538.     else if (self->spawnflags & 4)    //attack
  539.     {
  540.         other->enemy = G_PickTarget(self->pathtarget);
  541.         if (other->enemy)
  542.         {
  543.             other->goalentity = other->enemy;
  544.             if (self->spawnflags & 32)
  545.                 other->monsterinfo.aiflags |= AI_BRUTAL;
  546.             if (self->spawnflags & 16)
  547.             {
  548.                 other->monsterinfo.aiflags |= AI_STAND_GROUND;
  549.                 actor_stand (other);
  550.             }
  551.             else
  552.             {
  553.                 actor_run (other);
  554.             }
  555.         }
  556.     }
  557.  
  558.     if (!(self->spawnflags & 6) && (self->pathtarget))
  559.     {
  560.         char *savetarget;
  561.  
  562.         savetarget = self->target;
  563.         self->target = self->pathtarget;
  564.         G_UseTargets (self, other);
  565.         self->target = savetarget;
  566.     }
  567.  
  568.     other->movetarget = G_PickTarget(self->target);
  569.  
  570.     if (!other->goalentity)
  571.         other->goalentity = other->movetarget;
  572.  
  573.     if (!other->movetarget && !other->enemy)
  574.     {
  575.         other->monsterinfo.pausetime = level.time + 100000000;
  576.         other->monsterinfo.stand (other);
  577.     }
  578.     else if (other->movetarget == other->goalentity)
  579.     {
  580.         VectorSubtract (other->movetarget->s.origin, other->s.origin, v);
  581.         other->ideal_yaw = vectoyaw (v);
  582.     }
  583. }
  584.  
  585. void SP_target_actor (edict_t *self)
  586. {
  587.     if (!self->targetname)
  588.         gi.dprintf ("%s with no targetname at %s\n", self->classname, vtos(self->s.origin));
  589.  
  590.     self->solid = SOLID_TRIGGER;
  591.     self->touch = target_actor_touch;
  592.     VectorSet (self->mins, -8, -8, -8);
  593.     VectorSet (self->maxs, 8, 8, 8);
  594.     self->svflags = SVF_NOCLIENT;
  595.  
  596.     if (self->spawnflags & 1)
  597.     {
  598.         if (!self->speed)
  599.             self->speed = 200;
  600.         if (!st.height)
  601.             st.height = 200;
  602.         if (self->s.angles[YAW] == 0)
  603.             self->s.angles[YAW] = 360;
  604.         G_SetMovedir (self->s.angles, self->movedir);
  605.         self->movedir[2] = st.height;
  606.     }
  607.  
  608.     gi.linkentity (self);
  609. }
  610.